package com.tweetgraph.controller;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Logger;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.Query;
import com.tweetgraph.domain.BasicQuery;
import com.tweetgraph.domain.ResultAnalysis;
import com.tweetgraph.domain.ResultAnalysis.Terms;

public class ResultsProcessor extends HttpServlet {
	
	
	/**
	 * 
	 */
	private static final long serialVersionUID = -7909727278206480341L;

	private static Logger logger = Logger.getLogger(ResultsProcessor.class.getName());

	public void service(HttpServletRequest req,HttpServletResponse resp) {
		/*
		 * Get the hash tag -> get the query object and the tweets from the db for the hashtag
		 * process the results -> convert to JSON and write to the stream.
		 *  
		 */
		String hashTag = req.getParameter("hashTag");
		if(hashTag == null || "".equals(hashTag)){
			hashTag = (String)req.getAttribute("hashTag");
		}
		/*
		 * Check if there is an entity with the same #hashtag in the db
		 */
		Key key = KeyFactory.createKey("QueryResult", hashTag);
		DatastoreService datastore =  DatastoreServiceFactory.getDatastoreService();
		
		Entity existEnt = null;
		
		try{
			existEnt = datastore.get(key);
		}catch(EntityNotFoundException e){
			//do nothing 
		}
		
		if(existEnt == null){
			try{
				PrintWriter writer = resp.getWriter();
				writer.write("{\"Query Not Found\":\"100\"}");
				writer.flush();
			}catch(IOException e){
				e.printStackTrace();
			}
			return;
		}
		BasicQuery basicQuery = BasicQuery.getInstance(existEnt);
		
		/*
		 * Get the tweets for this query object.
		 */
		List<TGTweet> resultList = getTweetsFromDB(key,datastore);
		ResultAnalysis analysis = getResultAnalysis(resultList, basicQuery, hashTag);
		
		logger.info("The result analsysi JSON:"+ analysis.toJSONString());
		
		/*
		 * Put the analysis into response
		 */
		try{
			
			PrintWriter writer = resp.getWriter();
			writer.write(analysis.toJSONString());
			writer.flush();
		}catch(Exception e){
			e.printStackTrace();
		}
	}

	
	
	/**
	 * 
	 * @param list
	 * @param basicQuery
	 * @param hashTag
	 * @return
	 */
	private ResultAnalysis getResultAnalysis(List<TGTweet> list,BasicQuery basicQuery, String hashTag){
		ResultAnalysis analysis = new ResultAnalysis(hashTag);
		boolean match = false;
		
		for(String item:basicQuery.getKeywordSet()){
			if(item != null && !"".equals(item.trim())){
				analysis.addTerm(new ResultAnalysis.Terms(item));
			}
		}

		/*
		 * Set if others option is also being counted.
		 */
		analysis.setDoCountOther(basicQuery.isCountOther());
		
		
		/*
		 * Iterate through the tweets and increment counts on match
		 */
		for(TGTweet tweet:list){
			match = false;
			if(tweet != null && tweet.getText() != null){
				for(Terms term:analysis.getTermSet()){
					if(tweet.getText().toLowerCase().contains(term.getTerm().toLowerCase())){
						term.incrCount();
						match = true;
					}
				}
				/*
				 * If there is not a single match for this tweet and 
				 * we are counting others then increment the count for others.
				 */
				if(!match && analysis.isDoCountOther()){
					analysis.incrementOtherCount();
				}
			}
		}
			
		return analysis;	
	}

	
	

	private List<TGTweet> getTweetsFromDB(Key key, DatastoreService datastore){
		List<TGTweet> list = new ArrayList<TGTweet>();
		TGTweet tw = null;
		
		Query query = new Query("tweet",key);
		List<Entity> results = datastore.prepare(query).asList(FetchOptions.Builder.withLimit(500));
		for(Entity ent:results){
			try{
				tw = new TGTweet();
				
				tw.setId((Long)ent.getProperty("id"));
				tw.setText((String)ent.getProperty("text"));
				tw.setFromUser((String)ent.getProperty("fromUser"));
				tw.setToUser((String)ent.getProperty("toUser"));
				tw.setCreateDate((Date)ent.getProperty("createdDate"));
				tw.setLocation((String)ent.getProperty("location"));
			}catch(Exception e){
				e.printStackTrace();
			}
			
			list.add(tw);
		}
		return list;
	}
	
}
